昨天有講到一個叫做 getUpdates
的方法,但我們沒有填任何參數,今天要利用 offset 與 timeout 達成 Long Polling
先再執行一次昨天最後的程式,你會看到有個叫做 update_id
東西
把它填到 offset 的值,然後 timeout 先填 60,表示 60 秒以內 TG 伺服器要回應你
填好之後按下執行,你會發現和剛剛拿到的東西一模一樣,這是因為它會從你設定的 update_id
開始取訊息
我們把剛剛填的值加一,再執行看看
你會發現程式跑了整整一分鐘才跑完,而且啥都沒有,只有印出一個空陣列 Array()
這是因為 540834396
就是最後一則訊息了,並沒有 540834397
這則訊息
再執行一次程式,這次執行之後私訊機器人一則訊息
你會發現發送訊息後,TG 伺服器立刻就回應了,而且程式也馬上跑完了
這個就是 Long Polling
發出請求時,伺服器會一直到有新訊息時才會回應,或是到達時間限制(timeout)時回應空訊息
這樣不僅不用一直發送請求,而且有新訊息時也能立刻收到
我們再來試個東西,如果把 540834397
改回 540834396
看看會發生什麼事
按下執行後,你會發現 540834396
不見了,只剩 540834397
這是因為 TG 伺服器會把小於 offset 的 update_id
都當作是你已經處理過的了,並且將這些訊息捨棄,所以你就沒辦法再次讀取了
我們要用到 processMessage
這個官方範例裡的一個函式,這個函式裡要填的是 message
,但是要怎麼把它取出來呢?
首先第一步,把 print_r()
刪除,改成 $response =
,記得後面的括號要刪掉一個
把它照著層數接在 $response
的後面,message 是字串,所以要用引號 '
包起來
接好之後會像這樣
最後把 processMessage()
加上去,別忘了後面的小括號 )
和分號 ;
按下執行後你會發現它印出了一坨東西
{"chat_id":127355800,"reply_to_message_id":24,"text":"Cool","method":"sendMessage"}
這是因為它用了第三種發送訊息的方式,但現在程式並不是在 Webhook 模式下運作,所以就直接 echo 到終端機上了
我們只需要將第 139 行的 apiRequestWebhook
改成 apiRequest
就行了
改完再次執行程式,此時 TG 「叮咚」了一聲
成功用官方的函式處理了訊息
其實不只是 $response[0]
裡面有 message
,$response[1], $response[2]...
也會有 message
,至於會到數字多少,這取決於一次取到了多少則訊息
如果你發送了兩則訊息才執行一次程式,此時就會出現兩個 message
,那要如何每個 message
都處理到呢,這時候就要用到 foreach
這個函式,它會一個個的把裡面的東西交給你,直到全部完成為止
來稍微修改一下剛剛的程式,把 $response
交給 foreach
,中間的 $update
就是 $response[0], $response[1]...
(你可以用 print_r($update);
印出來看看),然後把 $update['message']
填進 processMessage()
函式中,記得加分號~
這樣每則訊息就都會處理到了
聰明的你應該已經發現了,不管執行幾次它都會重複處理訊息,因為它總是從 offset 開始處理
每次執行一次程式就要改一次 offset,這樣多麻煩,當然是要讓程式自己設定
首先要找出這很多則訊息的最後一則訊息,我們可以用 count($response)
知道總共有幾則訊息,count($response) - 1
表示最後一則(因為是從 0 開始數),我們先將這個值存進一個叫做 $latest
的變數裡
然後把 $latest
填進 $response
的第一個框框裡,第二個框框填上 'update_id'
,update_id 是字串,所以要用引號 '
包起來
這樣就取得了最後一則訊息的 update_id
我們是要把 offset 的值填下一則訊息的 update_id
,這樣才不會一直重複讀取同一則訊息,這邊只要在後方多打個 + 1
就行了,之後把計算的結果存進 $update_id
變數裡
還記得會有沒取到訊息的時候對吧,沒取到訊息時 $latest
的值會變成 -1
,但是框框裡不能出現負數,這時就要加個 if
條件 $latest !== -1
,有讀取到訊息時才把 update_id
取出來
再來就是把 $update_id
填到 offset 的值裡,還有加上 while (true) {}
,讓程式不斷重複執行
最後的最後,在最前面加上一行 $update_id = 0;
這樣就大功告成啦
執行程式後,試著跟機器人說 Hi、Hello 吧
對了,如果想要停止程式的話,就對著終端機按下 Ctrl + C
,程式就會停止了
今天的內容可能有點困難,看不太懂沒關係
如果沒辦法照著做出來的話,歡迎直接複製下方程式碼來玩玩:
$update_id = 0;
while (true) {
$response = apiRequest("getUpdates", array('offset' => $update_id, 'timeout' => 60));
foreach ($response as $update) {
processMessage($update['message']);
}
$latest = count($response) - 1;
if ($latest !== -1) {
$update_id = $response[$latest]['update_id'] + 1;
}
}
最後,再來考考你
如果少加了 $update_id = 0;
會發生什麼事?
在底下留言你的答案吧!